﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PServiceBus.Core.Security;
using System.Net.Http;
using System.Collections.Specialized;
using System.Web;
using System.Configuration;
using PServiceBus.Services.Web;
using System.Web.Http.Controllers;
using System.Threading.Tasks;
using System.Threading;
using System.Net;
using PServiceBus.Core.Logger;
using System.ServiceModel.Channels;

namespace PServiceBus.WebAPI.Controllers {
    public partial class ESBController {

        internal WebMessageBus MessageBus {
            get {
                return WebMessageBus.Select(ConnectionID, UserName, Password, Headers);
            }
        }

        private readonly static object _nullJson = new { };
        private HttpResponseMessage EmptyResponse {
            get {
                return Request.CreateResponse(HttpStatusCode.OK, _nullJson);
            }
        }

        public override Task<HttpResponseMessage> ExecuteAsync(HttpControllerContext controllerContext, CancellationToken cancellationToken) {
            var request = controllerContext.Request;
            if (request.Method == HttpMethod.Options) {
                var response = request.CreateResponse(HttpStatusCode.OK, _nullJson);
                SetHttpHeaders(response);
                var tcs = new TaskCompletionSource<HttpResponseMessage>();
                tcs.SetResult(response);
                return tcs.Task;
            }
            return base.ExecuteAsync(controllerContext, cancellationToken)
                .ContinueWith(task =>
                {
                    var response = task.Result;
                    if (!task.IsFaulted)
                        SetHttpHeaders(response);
                    else ESBLogger.Log(task.Exception);
                    return response;
                });
        }

        private void SetHttpHeaders(HttpResponseMessage response) {
            response.Headers.Add("Access-Control-Allow-Origin", "*");
            response.Headers.Add("Access-Control-Allow-Headers", "Content-Type, Content-Length, X-REQUESTED-WITH, X-REQUESTED-BY");
            response.Headers.Add("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS");
            response.Headers.Add("Access-Control-Max-Age", "1728000");
            response.Headers.Add("P3P", "CP=IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT");
            response.Headers.Add("Cache-Control", "no-cache, must-revalidate");
        }

        private NameValueCollection QueryString {
            get {
                return HttpUtility.ParseQueryString(Request.RequestUri.Query);
            }
        }

        private string ConnectionID {
            get {
                var connectionID = QueryString["ConnectionID"];
                return String.IsNullOrWhiteSpace(connectionID) ? "ESBREST" : connectionID;
            }
        }

        private bool ReThrowException {
            get {
                var reThrow = false;
                return Boolean.TryParse(QueryString["ReThrowException"], out reThrow) 
                    && reThrow;
            }
        }

        private Dictionary<string, string> Headers {
            get {
                var headers = new Dictionary<string, string>();
                headers["ConnectionID"] = ConnectionID;
                headers["UserName"] = UserName;
                headers["ClientToken"] = ClientToken;
                headers["ClientIpAddress"] = Request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name) ?
                    (Request.Properties[RemoteEndpointMessageProperty.Name]
                    as RemoteEndpointMessageProperty).Address : string.Empty;
                return headers;
            }
        }

        private string UserName {
            get {
                return QueryString["ESBUserName"];
            }
        }

        private string Password {
            get {
                return QueryString["ESBPassword"];
            }
        }

        private string ClientToken {
            get{
                return QueryString["ClientToken"];
            }
        }
    }
}
